PO
tfs 0.3

Tutorial Coroutine Lua

Por Poccnn, 20 de ago. de 2016 em Aulas

coroutine
tutorial
lua
8
3.9k
PoccnnP
20 de agosto de 2016 às 08:41

Fala Xtibianos. 
Nesse tutorial, gostaria de explicar um pouco sobre coroutine e seu uso. 

 

Irei começar com uma lista de funções da coroutine. 

Citar

coroutine.create (f)               cria uma nova coroutine com uma função lua valida. 
coroutine.yield (···)                suspende a execução da coroutine. 
coroutine.resume (co [, val1, ···])    passa os valores para a coroutine. 
coroutine.running ()                pega a coroutine que esteja em execução. 
coroutine.status (co)                return "suspended", "running" ou "dead"
coroutine.wrap (f)                   cria uma nova coroutine no corpo com uma função lua valida. 

 

Irei começa falando sobre a principal função da coroutine. 

Citar

coroutine.create (f) 

 

No corpo dessa função, voce precisa declarar pontos para "suspender" a execução da coroutine. 

 

Ao criar a coroutine, ela se encontra no estado "suspended", ou seja, parada/pausada. 


para iniciar a coroutine, voce precisa ativar ela usando a função: 

Citar

coroutine.resume (co [, val1, ···]) 

 

Além de ativar/reativar a coroutine, você passa valores para a função da coroutine. 
A primeira ativação da coroutine, os argumentos passados não poderão ser modificados, ficam estáticos nos parâmetros da função. 

 

Citar

 

co = coroutine.create(function(a,b) 
-- verificando o estatus da coroutine. 
   print(coroutine.status(coroutine.running())) -- "running" 
   coroutine.yield(a+b) -- primeira chamada 
   coroutine.yield(a-b) -- segunda chamada 
   return a,b,"Fim da coroutine." -- chamada final usando return (facultativo). 
end) 

 

-- verificando o estatus da coroutine. 
print(coroutine.status(co))       -- "suspended" 
print(coroutine.resume(co,5,2))    -- saida >> 7 >> 5+2 
print(coroutine.resume(co,1,8))    -- saida >> 3 >> ??? 1-8 = -7 
print(coroutine.resume(co,9,55))   -- saida >> 5,2, Fim da coroutine. >> veja que são os valores passados na primeira chamada. 
-- verificando o estatus da coroutine. 
print(coroutine.status(co))       -- "dead" 

 

 

Veja que o resultado da segunda chamada não coincidem com os valores passados. Isso se dá devido aos parâmetros da função impregada na coroutine, não modificar seus valores. uma vez declarados os valores, eles não poderão ser modificados. 

 

uma chamada de coroutine a mais da quantidade de yield's existente na coroutine.

Citar

print(coroutine.resume(co,9,55))   -- saida >> cannot resume dead coroutine

 

Como demonstrado acima, ao exceder a quantidade de yield's, ela retorna essa mensagem (sem disparar erro no console). 

 

Agora você deva estar se perguntando: Então como fazer para pegar os valores que são passados em cada ativação? 


Vou explicar agora: 

a função yield pega os valores fornecidos e retorna-os; então você pode pegar esses valores usando variaveis para armazena-los. 

Citar

 

co = coroutine.create(function(a,b) 
   b,c = coroutine.yield(a+b) -- primeira chamada 
   c,d = coroutine.yield(b-c) -- segunda chamada. veja que modifiquei os parametros usados. 
   return c,d,"Fim da coroutine." -- chamada final usando return (facultativo). 
end) 

print(coroutine.resume(co,5,2))    -- saida >> 7 >> 5+2 
print(coroutine.resume(co,1,8))    -- saida >> -7 >> 1-8 << agora o resultado está certo, pois foi usados os valores passados pela segunda chamada. 
print(coroutine.resume(co,9,55))   -- saida >> 9,55, Fim da coroutine. << os dois numerais, são os valores passados na ultima chamada.

 

 

 

Mas, no corpo da função criada para a coroutine, você pode fazer chamadas a funções, pegar valores de variaveis globais, etc; sempre usando a função yield para "suspender" a coroutine. 

 

Citar

 

function add(a,b) 
   return coroutine.yield(a+b,"Valor retornado pela função add()") 
end 

m,n = 2,3 

co = coroutine.create(function(a,b) 
   c,d = add(a,b) 
   e,f = add(m,n) 
   return e,f, "Fim da coroutine." -- retorna os valores da ultima chamada. 
end) 

print(coroutine.resume(co,5,2))    -- saida >> 7, "Valor retornado pela função add()" >> 5+2 
print(coroutine.resume(co,1,8))    -- saida >> 5 >> "Valor retornado pela função add()" >> valores pegos das variaveis externa 'm' e 'n' >> 2+3 
print(coroutine.resume(co,9,55))   -- saida >> 9,55, Fim da coroutine. << os dois numerais, são os valores passados na ultima chamada.

 

 

Agora só falta comentar sobre a função: 

Citar

coroutine.wrap(f)

 
Assim como coroutine.create, a função auxiliar coroutine.wrap cria uma nova co-rotina, mas ao invés de retornar uma referência para a co-rotina, retorna uma função que, quando chamada, (re)invoca a co- rotina. 


De forma geral, a função coroutine.wrap oferece uma maior conveniência que coroutine.create; ela provê exatamente o que é usualmente necessario: uma função para reativar uma co-rotina. Por outro lado, o uso das funções coroutine.create e coroutine.resume permite o gerenciamento de erros (funções estas que não podem ser usada por wrap). 

 

Citar

 

-- fatorar o valor 
function fatorar(n) 
   if n > 1 then 
      coroutine.yield(n) 
      fatorar(n/2) -- recursividade 
   end 
end 

-- iterador 
iterator = coroutine.wrap(function(value) 
      fatorar(value) 
   end) 

print(iterator(32)) -- 32 
print(iterator())   -- 16 
print(iterator())   -- 8 
print(iterator())   -- 4 
print(iterator())   -- 2 
print(iterator())   -- 1 
print(iterator())   -- Disparado erro com mensagem: "cannot resume dead coroutine". 

 


A função retornada por coroutine.wrap não captura erros; qualquer erro provocado pela execução da co-rotina é propagado a seu chamador. 

 

É isso ai pessoal, espero que tenham gostado. qualquer duvida, sugestão ou critica, deixem nos comentários. 
 

kttallanK
20 de agosto de 2016 às 11:44

Muito bom @Poccnn, sempre trazendo boas novidades relacionada a área de lua.

 

Queria eu poder exercer, mas é tenso aprender só :S.

PoccnnP
20 de agosto de 2016 às 12:37

@kttallan

Qual sua dificuldade em aprender? 

kttallanK
20 de agosto de 2016 às 15:41
2 horas atrás, Poccnn disse:

@kttallan

Qual sua dificuldade em aprender? 

Bom eu fazia codigos antigamente, participei da primeira escolinha de scripting do xtibia a qual o roksas era o professor aprendi tudo até criar funções, hoje sei da logica só que não sei muito sobre.

 

For, While e Repeat e Strings, Table, Creio que o resto eu saiba como criar funções etcs..

4 meses depois...
otteNO
08 de dezembro de 2016 às 21:33

O que é uma corrotina em lua? É tipo um thread?

4 meses depois...
26 de abril de 2017 às 11:38

amigao vc e genial porem sou um pouco leigo na area de programação.. poderia me explicar oque seria coroutine e em que tipo de situação é aplicado?

PoccnnP
26 de abril de 2017 às 13:26
Em 08/12/2016 at 21:33, newFag disse:

O que é uma corrotina em lua? É tipo um thread?

 

Não é uma thread. É um processo executado em modo separado.

 

1 hora atrás, Everson Miranda disse:

amigao vc e genial porem sou um pouco leigo na area de programação.. poderia me explicar oque seria coroutine e em que tipo de situação é aplicado?

 

Coroutine é uma forma de criar um processo que oode parar sua execução a qualquer momento e podendo retornar a execução a pedido do sistema.

É difícil fazer uma implementação dela no mundo do ot server, mas eu fiz essa:

 

 

2 meses depois...
PoccnnP
10 de junho de 2017 às 15:23

Caro membro,

Seu tópico foi movido de Tutoriais para Aulas.